import { BaseComp } from '../../../common/component/comp';
import { ZRenderComp } from '../../../common/component/zrComp';

import { FlightItem, FlightRecords } from '../../compute/flightRecords';
import { loadLayout, LayoutWraper, layouts } from './layouts';
import { VehicleTag } from './launchesComponents';
import { AbstractRow, rowFactory } from './rows';

import { parseColorText, gradientColor } from '../../../common/color/color';

/**
 * 这个 view 包括发射记录的所有内容, 包括发射记录行、年行,
 * 以及后续要加的各种资料行.
 * 
 * 记录行 (LaunchRow)、年行 (SummaryRow) 都将放到 LaunchList 中.
 * 
 * 后续如果你要补充新的资料行, 请创建一个类, 并且继承 AbstractRow
 * 
 * FlightLaunchesView
 * ├── Background (z-index=-1)
 * ├── 其它 rows (在 rows.js 中的)
 * └── LaunchList
 *     ├── LaunchRow (z-index=1,11)
 *     │   ├── VehicleTag (z-index=9,10,11)
 *     └── SummaryRow (z-index=1,11)
 *         └── VehicleTag (z-index=9,10,11)
 */

class FlightLaunchesView extends BaseComp {
  constructor(args) {
    super(null);
    this.context = args.context;
    /** @type {HTMLElement} */ this.dom = args.dom;
    this.zrender = args.zrender;
    this.zr = this.zrender.init(this.dom);
    /** @type {FlightRecords} */
    this.storage = args.storage;
    this.defer(() => this.zr.dispose());

    /** @type {LayoutWraper} */
    this.styleConfig = null;
    this.rowHeightChanged = false;
    this.on('view/rowHeight/changed', () => this.rowHeightChanged = true);

    // components
    /** @type {AbstractRow[]} */
    this.rows = [];
    this.bg = new Background({ parent : this, zr : this.zr, zrender : this.zrender });
    this.launchList = new LaunchList({
      parent : this, zr : this.zr, zrender : this.zrender,
      getStyle : () => this.styleConfig,
      y : layouts.position.panel.marginTop,
    });
    this.rows.push(this.launchList);
  }

  loadStyleConfig() {
    return Promise.resolve(this.styleConfig ? this.styleConfig : loadLayout(this.context));
  }

  /**
   * @param {FlightItem[]} items 
   */
  setRecords(items) {
    this.rowHeightChanged = false;
    this.loadStyleConfig()
      .then(style => this.styleConfig = style)
      .then(_ => this.launchList.refreshRows(items));
  }

  /**
   * @param {{type:string,params:object}[]} cards
   */
  setCards(cards) {
    // 除了 LaunchList 以外所有的 row 全部重建
    const {zrender, zr} = this;

    let rowsNeedDelete = this.rows.filter(r => r != this.launchList);
    rowsNeedDelete.forEach(r => r.destroy());
    this.rows = [];
    /** @type {{type:string,params:object}[]} */
    const results = [];

    for (let i = 0; i < cards.length; i++) {
      const card = cards[i];
      if (card.type === 'flights') {
        this.rows.push(this.launchList);
        results.push({type:card.type, params:{}});
        continue;
      }
      let row = rowFactory.create(card, { parent: this, zrender, zr });
      if (row == null) {
        continue;
      }
      this.rows.push(row);
      results.push(card);
    }

    this.adjustRows();
    return results;
  }

  resizeForAllLayers(width, height) {
    this.dom.style.width = width + 'px';
    this.dom.style.height = height + 'px';

    this.zr.resize({ width, height });
    let findCanvasAndResize = function(el) {
      if (el instanceof HTMLCanvasElement) {
        el.width = width;
        el.height = height;
        el.style.width = width + 'px';
        el.style.height = height + 'px';
      } else if (el instanceof HTMLDivElement) {
        let children = el.children;
        for (let i = 0; i < children.length; i++) {
          findCanvasAndResize(children[i]);
        }
      }
    }

    // 这可能是 bug, 需要手动将 canvas 重置大小, 而且重置之后 refresh 都不能重绘, 必须改变一下它元素的属性
    findCanvasAndResize(this.dom);
    this.emit('view/resize', { width, height });
  }

  adjustRows() {
    const {marginTop, width, marginBottom} = layouts.position.panel;

    let lastY = marginTop;
    for (let i = 0; i < this.rows.length; i++) {
      let row = this.rows[i];
      if (i != 0) {
        lastY += row.paddingTop;
      }
      row.y = lastY;
      lastY += row.adjustRows();
    }

    this.resizeForAllLayers(width, lastY + marginBottom);
  }

  tick() {
    if (this.rowHeightChanged) {
      this.adjustRows();
      this.rowHeightChanged = false;
    }
  }

  /**
   * @param {string} color
   */
  setBgColor(color) {
    this.bg.setBgColor(color);

    let rgb = parseColorText(color);
    if (rgb.a < 100) return;

    (rgb.r + rgb.g + rgb.b) / 3 < 100 ? this.styleConfig.useDarkTheme() : this.styleConfig.useLightTheme();
    this.emit('view/colorTheme/changed', this.styleConfig);
  }
}

class Background extends ZRenderComp {
  constructor(args) {
		super(args.parent, args.zrender);
    this.useExistZRenderInstance(args.zr, 0, 0);

    this.on('view/resize', (_, value) => {
      this.onResize(value);
    });
  }

  init() {
    this.black = this.createRect(layouts.position.panel.width, 1000)
      .fill('#FFF')
      .z(0, -10)
      .build();
  }

  onResize(args) {
    if (!this.hasInited) return;
    this.black.rectShape().height(args.height).update();
  }

  setBgColor(color) {
    if (!this.hasInited) return;
    this.black.style().fill(color).update();
  }
}

class LaunchList extends AbstractRow {
  constructor(args) {
    super(args);
    /** @type {() => LayoutWraper} */
    this.getStyle = args.getStyle;
    /** @type {AbstractRow[]} */
    this.rows = [];
    this.y = args.y;
    this.paddingTop = 40;
  }

  /**
   * @param {FlightItem[]} items 
   */
  refreshRows(items) {
    this.rows.forEach(row => row.destroy());
    this.rows = [];

    // 为每一个 rows 设置位置
    // 如果前后的 year 不同的话, 中间塞一个标签行
    let lastY = 0;
    let lastYear = 0;
    let lastMonth = 0;
    /** @type {SummaryRow} */
    let lastSummaryRow = null;
    // 为了美观, 每 3 行有一行是有从左到右的连接线, 需要有个计数器
    let lineCount = 0;
    const styleConfig = this.getStyle();
    
    for (let i = 0; i < items.length; i++) {
      const record = items[i];
      
      if (record.year != lastYear) {
        lastYear = record.year;
        
        // 创建 summary 行
        let srow = lastSummaryRow = new SummaryRow({
          parent : this,
          zr : this.zr,
          zrender : this.zrender,
          year: lastYear,
          colors : styleConfig,
        });
        this.rows.push(srow);
        srow.y = lastY;
        srow.x = layouts.position.panel.marginLeft;
        lastMonth = 0;
        lineCount = 0;
      }

      let row = new LaunchRow({
        parent : this,
        zr : this.zr,
        zrender : this.zrender,
        record,
        showMonth : record.month != lastMonth,
        colors : styleConfig,
        showAcrossLine : lineCount % 2 == 0,
      });
      lastSummaryRow.pushRecord(record);
      this.rows.push(row);
      lastMonth = record.month;
      row.x = layouts.position.panel.marginLeft;
      row.y = lastY;
      lineCount++;
    }

    this.adjustRows();
    this.emit('view/rowHeight/changed', {});
  }

  adjustRows() {
    let lastY = 0;
    for (let i = 0; i < this.rows.length; i++) {
      let row = this.rows[i];
      if (i != 0) {
        lastY += row.paddingTop;
      }
      row.y = lastY;
      lastY += row.adjustRows();
    }
    return this.height = lastY;
  }
}

class LaunchRow extends AbstractRow {
  constructor(args) {
    super(args);
    /** @type {FlightItem} */ this.record = args.record;
    /** @type {LayoutWraper} */ this.colors = args.colors;

    this.showMonth = (args.showMonth != false);
    this.showAcrossLine = (args.showAcrossLine != false);

    this.payloadHeight = 0;
    this.vehicleHeight = 0;

    this.on('view/colorTheme/changed', () => this.onThemeChanged());
  }

  init() {
    this.drawVehicle();
    this.drawOrbit();
    this.drawDay();
    this.drawPayloads();
    this.height = Math.max(this.vehicleHeight, this.payloadHeight);

    this.emit('view/rowHeight/changed', {});
  }

  drawVehicle() {
    const { colors, record } = this;
    const { vehicleX, vehicleY } = layouts.position.launchRow;
    const vehicleName = record.vehicles[0].name;
    const vehicleFontSize = layouts.font.launchRow.vehicleFontSize;
    this.vehicleHeight = layouts.position.launchRow.height;

    const style = record.isManned() ? colors.mannedVehicleStyle() : colors.vehicleStyle(vehicleName);
    const bgColor = this.vehicleColor = style.color;

    this.vehicle = new VehicleTag({
      x : vehicleX,
      y : vehicleY,
      parent : this,
      vehicle : record.vehicles[0].name,
      vehicleId : record.vehicles[0].id,
      color : bgColor,
      textColor : colors.launchRow.tagText,
      fontSize : vehicleFontSize,
      path : style.path,
    });

    // 处理 tag 下面的一行灰色小字
    let vehicleDescs = style.descList.concat();
    if (record.vehicles.length > 1) {
      vehicleDescs = vehicleDescs.concat(record.vehicles.slice(1).map(v => '+' + v.name + ' ' + v.id));
    }
    vehicleDescs.filter(v => v != '');

    if (vehicleDescs.length) {
      const {vehicleDescFontSize} = layouts.font.launchRow;
      this.createText(vehicleDescs.join(' | '), vehicleDescFontSize)
        .textFill(bgColor)
        .textStroke('#FFF', 1)
        .textStyle('left', 'top', 'normal', 'Impact')
        .position(vehicleX + vehicleFontSize / 3, (vehicleY + vehicleFontSize * 1.3) | 0)
        .z(0, 11)
        .build();
      this.vehicleHeight += vehicleDescFontSize;
    }
  }

  drawOrbit() {
    const { colors, record } = this;
    const { orbitHCOX, orbitGTOX, orbitMEOX, orbitLEOX, orbitY, orbitTextY,
      orbitText3TY, orbitText3BY
    } = layouts.position.launchRow;
    const { orbit1FontSize } = layouts.font.launchRow;

    /** 'L'EO 'G'TO 这个首字母的居中位置横坐标 */
    let xx = orbitLEOX;
    let tx1 = '', tx2 = '', tx3T = '', tx3B = '';

    const orbitStyle = colors.orbitStyle(record.orbit);
    if (orbitStyle) {
      tx1 = orbitStyle.texts[0];
      tx2 = orbitStyle.texts[1];

      const level = orbitStyle.level;
      xx = (level <= 2) ? ((level == 1) ? orbitLEOX : orbitMEOX) : ((level == 4) ? orbitHCOX : orbitGTOX);
    }

    /** orbit 的 tx1~4 部分最右边的横坐标 */
    let rightX = xx;
    /** vehicle 和 orbit 之间的连线, 右端点横坐标 */
    let lineRight = xx;

    record.orbitParam.split(' ')
        .filter(t => t != '')
        .forEach(t => {
          if (t === '天宫' || t === '太空实验室' || t === 'TMI') {
            tx2 = '/' + t;
            return;
          }

          if (t.endsWith('KM')) {
            tx3B = tx3B == '' ? t : t + ' ' + tx3B;
            return;
          }

          if (t.endsWith('°')) {
            tx3T = tx3T == '' ? t : t + ' ' + tx3T;
            return;
          }

          tx3T = tx3T == '' ? t : t + ' ' + tx3T;
        });

    if (record.success) {
      const spTx1 = this.createText(tx1, orbit1FontSize)
        .position(xx, orbitTextY + 1)
        .textStyle('center', 'bottom', 'bold', 'Arial Black')
        .opacity(record.success ? 1 : 0.3)
        .textShadow('#AAA6', 1, 2, 2)
        .z(0, 11)
        .textFill(orbitStyle.color)
        .build();
      const { width : tx1W } = spTx1.getBoundingRect();

      // 算这个部分包围盒最右边的 x
      rightX += (tx1W / 2 + 4);
      const spTx2 = this.createText(tx2, 20)
        .position(rightX, orbitTextY - 3)
        .textStyle('left', 'bottom', 'bold', 'Arial Black')
        .opacity(record.success ? 1 : 0.3)
        .textShadow('#AAA6', 1, 2, 2)
        .z(0, 11)
        .textFill(orbitStyle.color)
        .build();
      const { width : tx2W } = spTx2.getBoundingRect();
      rightX += (tx2W + 4);

      let tx3W = 0;
      if (tx3T) {
        const spTx3T = this.createText(tx3T, 14)
          .position(rightX, orbitText3TY)
          .textStyle('left', 'bottom', '100', 'Impact')
          .opacity(record.success ? 1 : 0.3)
          .z(0, 11)
          .textFill('#AAA')
          .build();
        tx3W = spTx3T.getBoundingRect().width;
      }
      if (tx3B) {
        const spTx3B = this.createText(tx3B, 14)
          .position(rightX, orbitText3BY)
          .textStyle('left', 'bottom', '100', 'Impact')
          .opacity(record.success ? 1 : 0.3)
          .z(0, 11)
          .textFill('#AAA')
          .build();
        tx3W = spTx3B.getBoundingRect().width > tx3W ? spTx3B.getBoundingRect().width : tx3W;
      }

      if (tx3W > 0) {
        rightX += (tx3W + 4);
      }

      lineRight -= tx1W / 2;
    } else {
      this.createPathFromString(colors.fallOrbit.path)
        .position(xx, orbitTextY - 1 - orbit1FontSize / 2)
        .z(0, 11)
        .fill(colors.fallOrbit.pathColor)
        .build();
      rightX += orbit1FontSize / 2;
    }

    const {
      siteSignXOffset, siteXOffset, siteY, payloadX,
    } = layouts.position.launchRow;

    // 淡色背景线.
    // 如果本次发射是成功的, 画淡色背景线.
    // 如果本次发射是失败的, 画斜线区域.
    this.orbitRightX = rightX + 5;
    if (record.success) {
      let yy = orbitY + 9;
      this.createLine(xx, yy, 50, yy)
        .stroke('#AAA3', 12)
        .z(0, 1)
        .build();
      if (this.showAcrossLine) {
        this.createLine(this.orbitRightX, yy, payloadX, yy)
          .stroke('#AAA3', 12)
          .lineDash([24, 8])
          .z(0, 1)
          .build();
      }
    } else {
      let ftoColor = parseColorText(colors.fallOrbit.pathColor);
      ftoColor.a = (255 * 0.2) | 0;

      const rectH = ((layouts.font.launchRow.payload1FontSize) * 1.2) | 0;
      const rectW = payloadX - 50;
      const spClip = this.createRect(rectW, rectH)
        .defineAsClip()
        .build();
      let slashX = 0;
      while (slashX < rectW) {
        let spSlish = this.createPolyline(
            [slashX, orbitY + rectH / 2],
            [slashX + 12, orbitY + rectH / 2],
            [slashX + 12 + rectH, orbitY - rectH / 2],
            [slashX + rectH, orbitY - rectH / 2])
          .fill(ftoColor.toHexRGBA())
          .stroke('#0000')
          .position(50, 0)
          .z(0, 0)
          .build();
        spSlish.setClipPath(spClip);
        slashX += 24;
      }
    }

    // 左边, 发射场
    this.createPathFromString('M5,0L-3,4V-4Z')
      .position(xx + siteSignXOffset, siteY)
      .z(0, 11)
      .fill('#AAA')
      .build();
    this.createText(record.site, layouts.font.launchRow.siteFontSize)
      .position(xx + siteXOffset, siteY)
      .textStyle('right', 'center', '300', 'Impact')
      .textShadow('#AAA', 0, 1, 1)
      .z(0, 11)
      .textFill('#666')
      .build();

    // 连线
    this.createLine(50, orbitY, lineRight, orbitY)
      .strokeLinearGradient(6, [0, 0, 1, 0], [
        { offset : 0.3, color : this.vehicleColor },
        { offset : 0.9, color : orbitStyle.color },
      ])
      .opacity(0.5)
      .lineDash([3, 3])
      .build();
  }

  drawDay() {
    const { record, colors, showMonth } = this;
    const {month, day, time} = record;
    const monthTx = `${month > 9 ? month + '' : '0' + month}-`;
    const dayTx = day > 9 ? day + '' : '0' + day;
    const textFill = colors.monthsColor[record.month];
    const {dayFontSize, timeFontSize} = layouts.font.launchRow;
    const {dayX, dayY} = layouts.position.launchRow;

    this.createText(monthTx, dayFontSize)
      .textFill(textFill)
      .textStyle('right', 'bottom', 'normal', 'Arial Black')
      .position(dayX, dayY)
      .opacity(showMonth ? 1 : 0.2)
      .z(0, 11)
      .build();
    this.createText(dayTx, dayFontSize)
      .textFill(textFill)
      .textStyle('left', 'bottom', 'normal', 'Arial Black')
      .position(dayX, dayY)
      .z(0, 11)
      .build();

    if (time != null) {
      this.createText(time, timeFontSize)
        .textFill(gradientColor(textFill, '#AAA', 0.8).toHexRGB())
        .textStyle('left', 'top', 'normal', 'Impact')
        .position(dayX, dayY)
        .z(0, 11)
        .build();
    }
  }

  drawPayloads() {
    const { record, colors } = this;
    const textFillColor = record.isImportant() ? this.vehicleColor : colors.launchRow.payload;
    const {
      payloadX : textRight, height, payloadMarginLeft, payloadTagMarginLeft, payloadTagY,
      payload2Y, payload1Y,
    } = layouts.position.launchRow;
    const {
      payload1FontSize, payload2FontSize
    } = layouts.font.launchRow;

    this.payloadHeight = height;
    let maxWidth = textRight - this.orbitRightX - payloadMarginLeft;

    let tags;
    let tagTexts = record.tags.concat();

    if (record.isPartialSuccess()) {
      tagTexts.push('部分成功');
    } else if (!record.success) {
      tagTexts.push('失败');
    }
    if (record.isManned()) {
      tagTexts.push('载人');
    }

    if (tagTexts.length) {
      let xx = this.orbitRightX + payloadMarginLeft;
      tags = tagTexts.map(tagText => {
        let massTag = new PayloadTag({
          parent: this,
          zrender: this.zrender,
          zr: this.zr,
          text: tagText,
          color: this.vehicleColor
        });
        massTag.x = xx;
        xx += (massTag.width + payloadTagMarginLeft);
        massTag.y = payloadTagY;
        maxWidth -= (massTag.width + payloadTagMarginLeft);
        return massTag;
      });
    };

    const textOpacity = record.payloads.length && record.success ? 1 : 0.3;
    const payloads = record.payloads.concat();
    if (payloads.length == 0) {
      payloads.push("无载荷");
    }

    let spPlTx = this.spPlTx = this.createText(payloads.join('    '), payload1FontSize)
      .textFill(textFillColor)
      .opacity(textOpacity)
      .textStyle('right', 'bottom', '500', '"Impact", "方正汉真广标简体"')
      .position(textRight, payload1Y)
      .build();

    let plTx2 = '';

    // 处理第一行文本
    const plTxW = spPlTx.getBoundingRect().width;
    if (plTxW <= maxWidth) {
      if (tags) {
        let xx = textRight - plTxW;
        tags.reverse().forEach(tag => {
          tag.x = xx - payloadTagMarginLeft - tag.width;
          xx -= (payloadTagMarginLeft + tag.width);
        });
      }
    } else if (plTxW <= maxWidth * 1.2) {
      spPlTx.scaleTo(maxWidth / plTxW, 1);
    } else {
      // 要特殊摆法了. 第一行摆到不能再摆为止, 后续的放第二行
      let countIn1stLine = 1;
      let plTxW2 = 0;
      for (; countIn1stLine <= payloads.length; countIn1stLine++) {
        spPlTx.style().text(payloads.slice(0, countIn1stLine).join('    ')).update();
        plTxW2 = spPlTx.getBoundingRect().width;
        if (plTxW2 > maxWidth * 1.2) {
          break;
        }
      }

      if (countIn1stLine == 1) {
        // 如果第一段文字都超过 maxWidth * 1.2, 那也别挣扎了, 第一行就这么长.
        spPlTx.scaleTo(maxWidth / plTxW2, 1);
      } else {
        countIn1stLine--;
        spPlTx.style().text(payloads.slice(0, countIn1stLine).join('    ')).update();
        plTxW2 = spPlTx.getBoundingRect().width;
        if (plTxW2 > maxWidth) {
          spPlTx.scaleTo(maxWidth / plTxW2, 1);
        }
      }

      plTx2 = payloads.slice(countIn1stLine).join('    ');
    }

    // 处理第二行文本
    // 剩余的文字挪到第二行, 第二行字体小很多
    // 另外, maxWidth 需要重新计算, 不计入 massTag 的长
    maxWidth = textRight - this.orbitRightX - payloadMarginLeft;
    if (record.payloadCount) {
      plTx2 += '  |  共 ' + record.payloadCount + ' 颗卫星';
    }
    if (record.mass) {
      plTx2 += '  |  总载重：' + record.mass;
    }
    if (record.desc) {
      for (let key in record.desc) {
        let v = record.desc[key];
        if (v instanceof Array) {
          plTx2 += '  |  ' + key + '：' + v.join('、');
        } else {
          plTx2 += '  |  ' + key + '：' + v;
        }
      }
    }

    if (!plTx2) {
      return;
    }

    let spPlTx2 = this.spPlTx2 = this.createText(plTx2, payload2FontSize)
      .textFill(textFillColor)
      .opacity(textOpacity)
      .textStyle('right', 'bottom', '500', '"Impact", "Microsoft YaHei UI"')
      .position(textRight, payload2Y)
      .build();
    const plTx2W = spPlTx2.getBoundingRect().width;
    if (plTx2W > maxWidth) {
      spPlTx2.scaleTo(maxWidth / plTx2W, 1);
    }

    // 另外, 本行的行高需要重新计算
    this.payloadHeight += (payload2Y - payload1Y);
  }

  onThemeChanged() {
    const { colors, record } = this;

    const textFillColor = record.isImportant() ? this.vehicleColor : colors.launchRow.payload;
    this.spPlTx && this.spPlTx.style().textFill(textFillColor).update();
    this.spPlTx2 && this.spPlTx2.style().textFill(textFillColor).update();

    this.vehicleColor = colors.vehicleStyle(record.vehicles[0].name).color;
    this.vehicle.changeColor(bgColor, colors.launchRow.tagText)
  }
}

class SummaryRow extends AbstractRow {
  constructor(args) {
    super(args);
    /** @type {number} */ this.year = args.year;
    /** @type {FlightItem[]} */ this.records = [];
    /** @type {LayoutWraper} */ this.colors = args.colors;
  }

  pushRecord(record) {
    this.records.push(record);
  }

  init() {
    this.drawYear();
    this.drawStatistics();
    this.drawBg();
  }

  makeStatistics() {
    const {records} = this;

    let items = Array.from(new Set(records.map(r => r.vehicles[0].name)))
      .map(name => {
        let rs = records.filter(r => r.vehicles[0].name == name);
        return new VehicleStatisticsItem(
          name, rs.length, rs.reduce((p, r) => p + (r.success ? 1 : 0), 0));
      });
    items.sort((a, b) => (a.count == b.count) ? a.success - b.success : a.count - b.count).reverse();

    return {
      count: records.length,
      success: records.filter(r => r.success).length,
      items
    }
  }

  drawYear() {
    const {yearX, yearY} = layouts.position.summaryRow;
    this.createText(`${this.year}`, layouts.font.summaryRow.yearFontSize)
      .textFill('#AAA')
      .textStyle('left', 'top', 'oblique', 'Impact')
      .position(yearX, yearY)
      .z(0, 11)
      .build();
  }

  drawBg() {
    const {width, marginLeft, marginRight} = layouts.position.panel;
    this.createRect(width - marginLeft - marginRight, this.height - 40, 0, 20)
      .fill('#AAA')
      .opacity(0.2)
      .z(0, 9)
      .build();
  }

  drawStatistics() {
    const {colors} = this;
    const {width, marginLeft, marginRight} = layouts.position.panel;
    const {allFontSize1, allFontSize2, itemFontSize1, itemFontSize2} = layouts.font.summaryRow;
    const {
      allX, allY1, allY2, itemStartX, itemStartY, itemStartYOffset, itemHeight, itemMarginLeft,
    } = layouts.position.summaryRow;
    let items = this.makeStatistics();

    this.createText('成功次数 / 总任务数', allFontSize1)
      .textFill('#AAA')
      .position(allX, allY1)
      .opacity(0.7)
      .textStyle('center', 'bottom', 'bold', 'Microsoft YaHei UI')
      .z(0, 10)
      .build();
    this.createText(`${items.success} / ${items.count}`, allFontSize2)
      .textFill('#AAA')
      .position(allX, allY2)
      .opacity(0.7)
      .textStyle('center', 'bottom', '200', 'Impact')
      .z(0, 10)
      .build();

    let x = itemStartX;
    let y = itemStartY;
    items.items.forEach(item => {
      if (x > width - marginLeft - marginRight - 40) {
        x = itemStartX;
        y += itemStartYOffset;
      }

      let bgColor = colors.vehicleStyle(item.name).color;

      let tag = new VehicleTag({
        parent: this,
        zrender: this.zrender,
        zr: this.zr,
        vehicle: item.name,
        color: bgColor,
        fontSize: itemFontSize1,
      });

      this.createText(`${item.success} / ${item.count}`, itemFontSize2)
        .textFill(bgColor)
        .position(x + tag.width / 2, y + itemHeight)
        .opacity(0.7)
        .textStyle('center', 'bottom', '200', 'Impact')
        .z(0, 10)
        .build();

      tag.x = x;
      tag.y = y;
      x += tag.width + itemMarginLeft;
    });

    this.height = y + 66;
    if (this.height < 128) {
      this.height = 128;
    }
    this.emit('view/rowHeight/changed', {});
  }
}

class VehicleStatisticsItem {
  constructor(name, count, success) {
    /** @type {string} */ this.name = name;
    /** @type {number} */ this.count = count;
    /** @type {number} */ this.success = success;
  }
}

class PayloadTag extends ZRenderComp {
  constructor(args) {
    super(args.parent, args.zrender);
    this.useExistZRenderInstance(args.zr, 0, 0);

    /** @type {string} */ const text = this.text = args.text;
    /** @type {string} */ const color = this.color = args.color;

    const rectHeight = 20;

    let spTx = this.createText(text, 14)
      .textFill('#FFF')
      .textStyle('left', 'top', '300', '"Consolas", "Microsoft YaHei UI"')
      .z(0, 11)
      .position(3, 4)
      .build();
    const { width : innerW } = spTx.getBoundingRect();

    // 内层
    this.createRect(innerW + 6, rectHeight, 0, 0, [4, 4, 4, 4])
      .fill(color)
      .z(0, 10)
      .build();
    this.width = innerW + 12;
  }
}

export {
  FlightLaunchesView
};
